package com.thiswhyme.common.utils;

import lombok.NonNull;
import org.apache.commons.collections4.ListUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created by thiswhyme on 2020/05/09.
 */
public class StreamUtil {

    /**
     * list转map
     *
     * @param list
     * @param keyMapper
     * @param valueMapper
     * @param mergeFunction
     * @param <T>
     * @param <RK>
     * @param <RV>
     * @return
     */
    public static <T, RK, RV> Map<RK, RV> listToMap(List<T> list,
                                                    Function<? super T, ? extends RK> keyMapper,
                                                    Function<? super T, ? extends RV> valueMapper,
                                                    BinaryOperator<RV> mergeFunction) {
        return ListUtils.emptyIfNull(list)
                .stream()
                .collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction));
    }

    /**
     * list转map（带过滤）
     *
     * @param list
     * @param predicate
     * @param keyMapper
     * @param valueMapper
     * @param mergeFunction
     * @param <T>
     * @param <RK>
     * @param <RV>
     * @return
     */
    public static <T, RK, RV> Map<RK, RV> listToMap(List<T> list,
                                                    Predicate<T> predicate,
                                                    Function<? super T, ? extends RK> keyMapper,
                                                    Function<? super T, ? extends RV> valueMapper,
                                                    BinaryOperator<RV> mergeFunction) {
        return ListUtils.emptyIfNull(list)
                .stream()
                .filter(predicate)
                .collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction));
    }

    /**
     * list转map（同key value取最后一次）
     *
     * @param list
     * @param keyMapper
     * @param valueMapper
     * @param <T>
     * @param <RK>
     * @param <RV>
     * @return
     */
    public static <T, RK, RV> Map<RK, RV> listToMap(List<T> list,
                                                    Function<? super T, ? extends RK> keyMapper,
                                                    Function<? super T, ? extends RV> valueMapper) {
        return listToMap(list, keyMapper, valueMapper, (n1, n2) -> n2);
    }

    /**
     * list转map（同key value取最后一次，带过滤）
     *
     * @param list
     * @param predicate
     * @param keyMapper
     * @param valueMapper
     * @param <T>
     * @param <RK>
     * @param <RV>
     * @return
     */
    public static <T, RK, RV> Map<RK, RV> listToMap(List<T> list,
                                                    Predicate<T> predicate,
                                                    Function<? super T, ? extends RK> keyMapper,
                                                    Function<? super T, ? extends RV> valueMapper) {
        return listToMap(list, predicate, keyMapper, valueMapper, (n1, n2) -> n2);
    }

    /**
     * list转list
     *
     * @param list
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> listToList(List<T> list, Function<? super T, ? extends R> mapper) {
        return ListUtils.emptyIfNull(list)
                .stream()
                .map(mapper)
                .collect(Collectors.toList());
    }

    /**
     * list转set
     *
     * @param list
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Set<R> listToSet(List<T> list, Function<? super T, ? extends R> mapper) {
        return ListUtils.emptyIfNull(list)
                .stream()
                .map(mapper)
                .collect(Collectors.toSet());
    }

    /**
     * 过滤
     *
     * @param list
     * @param predicate
     * @param <T>
     * @return
     */
    public static <T> List<T> filter(@NonNull List<T> list, Predicate<T> predicate) {
        return ListUtils.emptyIfNull(list)
                .stream()
                .filter(predicate)
                .collect(Collectors.toList());
    }

    /**
     * 去重
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<T> distinct(List<T> list) {
        return ListUtils.emptyIfNull(list)
                .stream()
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 循环执行回调
     *
     * @param list
     * @param consumer
     * @param <T>
     * @return
     */
    public static <T> List<T> forEach(List<T> list, Consumer<T> consumer) {
        ListUtils.emptyIfNull(list).forEach(consumer);
        return list;
    }
}
